#include "MatrixMultiply.h"
#include "Matrix.h"
#include <climits>
#include <ctime>
#include <cfloat>
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <omp.h>
#include <math.h>
using namespace std;

extern unsigned int matrices;

int main(void)
{
	int maxCount = 2000;
	const int num_threads = 1;
	omp_set_num_threads(num_threads);
	double timeTableDGEMM[maxCount];
	double timeTableDGEMMV1[maxCount];
	double timeTableDGEMMV2[maxCount];
	double timeTableDGEMMV3[maxCount];
//Multiplikation DGEMM
	for(int n=96; n <= maxCount; n++)	
	{
		(n > 799) ? n+11 : n = n;
		int ld = (n%2) ? n : n+1;
		Matrix matA(n, ld);
		Matrix matB(n, ld);
		Matrix matC(n, ld);
		MatrixMultiply mm(&matA, &matB, &matC);
// 2.4218e-10*n*n*n + 2.2926e-08*n*n -1.4242e-06*n + 1.2534e-04

		int iter = 5;//max(1, (int)round(0.02/(2.4218e-10*n*n*n + 2.2926e-08*n*n -1.4242e-06*n + 1.2534e-04)));
		double time = (double)FLT_MAX;
		for(int rep = 0; rep < 2; rep++)
		{
			double start = omp_get_wtime();
			for(int its=0; its < iter; its++)			
				mm.cblas_myDGEMM();

			double stop = omp_get_wtime();
			double t = ((double)(stop-start))/iter;
			time = min(time, t);
		}
		cout << n << " / DGEMM" << endl;
//		cout << matC << endl;			
		timeTableDGEMM[n-1] = time;
	}
//pa v1
	for(int n=96; n <= maxCount; n++)	
	{
		(n > 799) ? n+11 : n = n;
		int ld = (n%2) ? n : n+1;
		Matrix matA(n, ld);
		Matrix matB(n, ld);
		Matrix matC(n, ld);
		MatrixMultiply mm(&matA, &matB, &matC);
// 2.4218e-10*n*n*n + 2.2926e-08*n*n -1.4242e-06*n + 1.2534e-04

		int iter = 5;//max(1, (int)round(0.02/(2.4218e-10*n*n*n + 2.2926e-08*n*n -1.4242e-06*n + 1.2534e-04)));
		double time = (double)FLT_MAX;
		for(int rep = 0; rep < 2; rep++)
		{
			double start = omp_get_wtime();
			for(int its=0; its < iter; its++)			
				mm.Parallel_DGEMMV1(num_threads);

			double stop = omp_get_wtime();
			double t = ((double)(stop-start))/iter;
			time = min(time, t);
		}
		cout << n << " / DGEMM" << endl;
//		cout << matC << endl;			
		timeTableDGEMMV1[n-1] = time;
	}
	//v2
	for(int n=96; n <= maxCount; n++)	
	{
		(n > 799) ? n+11 : n = n;
		int ld = (n%2) ? n : n+1;
		Matrix matA(n, ld);
		Matrix matB(n, ld);
		Matrix matC(n, ld);
		MatrixMultiply mm(&matA, &matB, &matC);
// 2.4218e-10*n*n*n + 2.2926e-08*n*n -1.4242e-06*n + 1.2534e-04

		int iter = 5;//max(1, (int)round(0.02/(2.4218e-10*n*n*n + 2.2926e-08*n*n -1.4242e-06*n + 1.2534e-04)));
		double time = (double)FLT_MAX;
		for(int rep = 0; rep < 2; rep++)
		{
			double start = omp_get_wtime();
			for(int its=0; its < iter; its++)			
				mm.Parallel_DGEMMV2(num_threads);

			double stop = omp_get_wtime();
			double t = ((double)(stop-start))/iter;
			time = min(time, t);
		}
		cout << n << " / DGEMMV2" << endl;	
//		cout << matC << endl;	
		timeTableDGEMMV2[n-1] = time;
	}
	//v3
	for(int n=96; n <= maxCount; n++)	
	{
		(n > 799) ? n+11 : n = n;
		int ld = (n%2) ? n : n+1;
		Matrix matA(n, ld);
		Matrix matB(n, ld);
		Matrix matC(n, ld);
		MatrixMultiply mm(&matA, &matB, &matC);
// 2.4218e-10*n*n*n + 2.2926e-08*n*n -1.4242e-06*n + 1.2534e-04

		int iter = 5;//max(1, (int)round(0.02/(2.4218e-10*n*n*n + 2.2926e-08*n*n -1.4242e-06*n + 1.2534e-04)));
		double time = (double)FLT_MAX;
		for(int rep = 0; rep < 2; rep++)
		{
			double start = omp_get_wtime();
			for(int its=0; its < iter; its++)			
				mm.Parallel_DGEMMV3(num_threads);

			double stop = omp_get_wtime();
			double t = ((double)(stop-start))/iter;
			time = min(time, t);
		}
		cout << n << " / DGEMMV3" << endl;
//		cout << matC << endl;			
		timeTableDGEMMV3[n-1] = time;
	}
//	double *matCContent = matC->GetMatrix();
//	int sizeOfC = matC->GetLD()*matC->GetRowCount();
/*	fstream myfile;
	myfile.open("Rene Eichert ZeitenMessung.txt", ios::out | ios::binary | ios::trunc);
	//FileHead
	myfile << "Problemgroesse\tSequentiell\tMethode1\tMethode2\tMethode3" << endl;
	for(int i = 0; i < maxCount; i++)
	{
		myfile << i << "\t" << timeTableDGEMM[i] << endl;
	}			
	myfile.close();
*/
	cout << "Done with the Measuring, press Enter to Exit" << endl;
	cin.get();
	return 0;
}
